﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.Profinet.Melsec;

namespace WinForm_fx3u_test
{
    public partial class Form1 : Form
    {
        //定义PLC对象
        private MelsecFxSerial FxSerial = new MelsecFxSerial();
        //定义obj用于进程锁
        private object obj = new object();
        //定义定时器
        System.Timers.Timer timer = new System.Timers.Timer();
        //用于调试
        Stopwatch sw = new Stopwatch();

        public Form1()
        {
            InitializeComponent();
        }

        private bool Write_Bool(string addr,bool bVal)
        {
            bool res = false;
            lock (obj)
            {
                if (FxSerial.IsOpen() == true)
                {
                    OperateResult Write_res = FxSerial.Write(addr, bVal);
                    if (Write_res.IsSuccess)
                    {
                        //MessageBox.Show("写入成功");
                        res=  true;
                    }
                }
                else
                {
                    timer.Stop();
                    MessageBox.Show("串口已关闭");
                }
                return res;
            }
        }
        private void Lbl_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Right)
            {
                Write_Bool(((Label)sender).Text, (((Label)sender).BackColor == Color.Red) ? true : false);
            }
        }
        
        /// <summary>
        /// 声明一个带参数的委托
        /// </summary>
        /// <param name="bool_res"></param>
        /// <param name="addrType"></param>
        public delegate void MyInvoke(bool[] bool_res,string addrType);

        /// <summary>
        /// X区、Y区、M区 lbl背景色更新（用来指示各存储区位变量状态）
        /// </summary>
        /// <param name="bool_res"></param>
        /// <param name="addrType"></param>
        public void UpdateForm(bool[] bool_res, string addrType)
        {
            switch (addrType)
            {
                case "X":
                    if (this.IsHandleCreated)
                    {
                        this.Invoke(new Action(() =>
                        {
                            foreach (var c in groupBox3.Controls)
                            {
                                if (c is Label)
                                {
                                    ((Label)c).BackColor = bool_res[int.Parse(((Label)c).Text.Substring(1, 1))] ? Color.Green : Color.Red;
                                }
                            }
                        }));
                    }
                    break;
                case "M":
                    if (this.IsHandleCreated)
                    {
                        this.Invoke(new Action(() =>
                        {
                            foreach (var c in groupBox5.Controls)
                            {
                                if (c is Label)
                                {
                                    ((Label)c).BackColor = bool_res[int.Parse(((Label)c).Text.Substring(1, 1))] ? Color.Green : Color.Red;
                                }
                            }
                        }));
                    }
                    break;
                case "Y":
                    if (this.IsHandleCreated)
                    {
                        this.Invoke(new Action(() =>
                        {
                            foreach (var c in groupBox4.Controls)
                            {
                                if (c is Label)
                                {
                                    ((Label)c).BackColor = bool_res[int.Parse(((Label)c).Text.Substring(1, 1))] ? Color.Green : Color.Red;
                                }
                            }
                        }));
                    }
                    break;
                default:
                    break;
            }

        }

        /// <summary>
        /// 定时器事件处理程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void onTimerTrig(object sender, ElapsedEventArgs e)
        {
            //周期读取变量
            //Color color = new Color();
            sw.Restart();
            lock (obj)
            {
                if (FxSerial.IsOpen() == true)
                {
                    // 读M区
                    try
                    {
                        OperateResult<bool[]> Read_res = FxSerial.ReadBool("m0", 8);
                        if (Read_res.IsSuccess)
                        {
                            bool[] read_bool_res = Read_res.Content;
                            MyInvoke mi = new MyInvoke(UpdateForm);
                            this.BeginInvoke(mi, new Object[] { read_bool_res, "M" });
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }

                    // 读Y区
                    try
                    {
                        OperateResult<bool[]> Read_res = FxSerial.ReadBool("y0", 8);
                        if (Read_res.IsSuccess)
                        {
                            bool[] read_bool_res = Read_res.Content;
                            MyInvoke mi = new MyInvoke(UpdateForm);
                            this.BeginInvoke(mi, new Object[] { read_bool_res, "Y" });
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }

                    // 读X区
                    try
                    {
                        OperateResult<bool[]> Read_res = FxSerial.ReadBool("x0", 8);
                        if (Read_res.IsSuccess)
                        {
                            bool[] read_bool_res = Read_res.Content;
                            MyInvoke mi = new MyInvoke(UpdateForm);
                            this.BeginInvoke(mi, new Object[] { read_bool_res, "X" });
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }

                }
                else
                {
                    MessageBox.Show("串口已关闭");
                    timer.Stop();
                }

            }
            sw.Stop();
            Console.WriteLine("time= {0}", sw.ElapsedMilliseconds.ToString());
        }

        /// <summary>
        /// 连接串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            FxSerial.SerialPortInni(sp =>
            {
                sp.PortName = tbx_port.Text;
                sp.BaudRate = int.Parse(cbx_baud.Text) ;
                sp.DataBits = 7;
                sp.StopBits = System.IO.Ports.StopBits.One;
                sp.Parity = System.IO.Ports.Parity.Even;
            }
            );
            try
            {
                FxSerial.Open();
                timer.Start();
                MessageBox.Show("串口打开！");
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }

        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            FxSerial.Close();
            FxSerial.Dispose();
            timer.Stop();
            MessageBox.Show("串口关闭");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //定时器初始化
            timer.Elapsed += new System.Timers.ElapsedEventHandler(onTimerTrig);
            timer.AutoReset = true;
            timer.Interval = 200;
            timer.Enabled = false;

            lbl_y0.BackColor = Color.Red;
            lbl_y1.BackColor = Color.Red;
            lbl_y2.BackColor = Color.Red;
            lbl_y3.BackColor = Color.Red;
            lbl_y4.BackColor = Color.Red;
            lbl_y5.BackColor = Color.Red;
            lbl_y6.BackColor = Color.Red;
            lbl_y7.BackColor = Color.Red;

            lbl_y0.MouseDown += Lbl_MouseDown;
            lbl_y1.MouseDown += Lbl_MouseDown;
            lbl_y2.MouseDown += Lbl_MouseDown;
            lbl_y3.MouseDown += Lbl_MouseDown;
            lbl_y4.MouseDown += Lbl_MouseDown;
            lbl_y5.MouseDown += Lbl_MouseDown;
            lbl_y6.MouseDown += Lbl_MouseDown;
            lbl_y7.MouseDown += Lbl_MouseDown;

            lbl_m0.BackColor = Color.Red;
            lbl_m1.BackColor = Color.Red;
            lbl_m2.BackColor = Color.Red;
            lbl_m3.BackColor = Color.Red;
            lbl_m4.BackColor = Color.Red;
            lbl_m5.BackColor = Color.Red;
            lbl_m6.BackColor = Color.Red;
            lbl_m7.BackColor = Color.Red;

            lbl_m0.MouseDown += Lbl_MouseDown;
            lbl_m1.MouseDown += Lbl_MouseDown;
            lbl_m2.MouseDown += Lbl_MouseDown;
            lbl_m3.MouseDown += Lbl_MouseDown;
            lbl_m4.MouseDown += Lbl_MouseDown;
            lbl_m5.MouseDown += Lbl_MouseDown;
            lbl_m6.MouseDown += Lbl_MouseDown;
            lbl_m7.MouseDown += Lbl_MouseDown;
        }
    }
}
